//
//  ERMethod.m
//  metadata
//
//  Created by easy on 11-5-30.
//  Copyright 2011 zeasy@qq.com. All rights reserved.
//

#import "ERMethod.h"
#import "ERSelector.h"
#import "ERClassType.h"
@implementation ERMethod
@synthesize source;
@synthesize name;
@synthesize numberOfArgument;
@synthesize returnType;
@synthesize argumentTypes;
@synthesize implementations;
@synthesize numberOfArgumentWithObject;
@synthesize argumentTypesWithObject;
-(id) initWithMethod:(Method) method{
	if (self = [super init]) {
		source = method;
	}
	return self;
}

-(void) exchangeImplementations:(ERMethod *) method{
	method_exchangeImplementations(self.source, method.source);
}

-(ERClassType *) argumentTypeAtIndex:(NSUInteger) index{
	return [self.argumentTypes objectAtIndex:index];
}

-(ERClassType *) argumentTypeWithObjectAtIndex:(NSUInteger) index{
	return [self.argumentTypes objectAtIndex:index + 2];
}

-(NSUInteger) numberOfArgumentWithObject{
	return self.numberOfArgument - 2;
}

-(NSArray *) argumentTypesWithObject{
	NSMutableArray *arr = [[NSMutableArray alloc] initWithCapacity:[self numberOfArgumentWithObject]];
	for (int i = 0; i < [self numberOfArgumentWithObject]; i++) {
		[arr addObject:[self.argumentTypes objectAtIndex:i+2]];
	}
	return [arr autorelease];
}

#pragma mark property setter/getter
-(ERMethodEntity *) entity{
	if (!entity) {
		entity = [[ERMethodEntity entityWithMethod:self.source] retain];
	}
	return entity;
}
-(NSString *) name{
	return [self entity].name;
}
-(NSUInteger) numberOfArgument{
	return [self entity].numberOfArgument;
}
-(ERClassType *) returnType{
	return [self entity].returnType;
}
-(NSArray *) argumentTypes{
	return [self entity].argumentTypes;
}
-(IMP) implementations{
	return method_getImplementation(self.source);
}
-(void) setImplementations:(IMP) imp{
	method_setImplementation(self.source, imp);
}
-(void) dealloc{
	source = nil;
	[entity release];
	[super dealloc];
}
@end


@implementation ERMethodEntity
@synthesize name;
@synthesize argumentTypes;
@synthesize returnType;
@synthesize numberOfArgument;

-(id) initWithName:(NSString *) aName argumentTypes:(NSArray *) argTypes returnType:(ERClassType *) rtnType{
	if (self = [super init]) {
		self.name = aName;		//retain
		self.argumentTypes = [[NSMutableArray alloc] initWithArray:argTypes];//alloc
		self.returnType = rtnType;	//retain
		numberOfArgument = [self.argumentTypes count];
	}
	return self;
}
+(id) entityWithMethod:(Method) method{
	NSString *aName = [ERSelector getName:method_getName(method)];
	char rtype[ER_MAX_ARRAY_SIZE];
	method_getReturnType(method, rtype, ER_MAX_ARRAY_SIZE);
	NSString *rstype = ER_STRING_ALLOC(rtype);
	ERClassType *rctype = [[ERClassType alloc] initWithType:rstype]; 
	[rstype release];
	unsigned int number = method_getNumberOfArguments(method);
	NSMutableArray *argTypes = [[NSMutableArray alloc] initWithCapacity:number];
	
	for (int i = 0; i < number ; i++) {
		char atype[ER_MAX_ARRAY_SIZE];
		method_getArgumentType(method, i, atype, ER_MAX_ARRAY_SIZE);
		NSString *astype = ER_STRING_ALLOC(atype);
		ERClassType *actype = [[ERClassType alloc] initWithType:astype];
		[argTypes addObject:actype];
		[actype release];
		[astype release];
	}
	ERMethodEntity *entity = [[ERMethodEntity alloc] initWithName:aName argumentTypes:argTypes returnType:rctype];
	[argTypes release];
	[rctype release];
	return [entity autorelease];
}
-(NSUInteger) numberOfArgument{
	return [self.argumentTypes count];
}
-(void) dealloc{
	[name release];
	[returnType release];
	[argumentTypes release];
	[super dealloc];
}
@end
